<!doctype html>
<html lang="zh-CN">
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <meta name="referrer" content="no-referrer-when-downgrade">
    

    <title>Flutter持久化存储之使用和封装shared_preferences | 早起的年轻人</title>
    <meta property="og:title" content="Flutter持久化存储之使用和封装shared_preferences - 早起的年轻人">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content='2021-08-31T13:27:35&#43;08:00'>
        
        
    <meta property="article:modified_time" content='2021-08-31T13:27:35&#43;08:00'>
        
    <meta name="Keywords" content="Flutter，golang,go语言,go语言笔记,飞雪无情,java,android,博客,项目管理,python,软件架构,公众号,小程序">
    <meta name="description" content="Flutter持久化存储之使用和封装shared_preferences">
        
    <meta name="author" content="luckly">
    <meta property="og:url" content="https://luckly.work/post/flutter_package/Flutter%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8%E4%B9%8B%E4%BD%BF%E7%94%A8%E5%92%8C%E5%B0%81%E8%A3%85shared_preferences/">
    <link rel="shortcut icon" href='/favicon.ico'  type="image/x-icon">

    <link rel="stylesheet" href='/css/normalize.css'>
    <link rel="stylesheet" href='/css/style.css'>
    <script type="text/javascript" src="//cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    
    
    
        <link href="https://cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css" rel="stylesheet">
    
    
    
    
        <link rel="stylesheet" href='/css/douban.css'>
    
        <link rel="stylesheet" href='/css/other.css'>
    
</head>

<link rel="stylesheet"
      href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js"></script>
<body>
    <header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="https://luckly.work/">
                        早起的年轻人
                    </a>
                
                <p class="description">专注于Flutter、Android、Java、Go语言(golang)、移动互联网、项目管理、软件架构</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="current" href="https://luckly.work/">首页</a>
                    
                    <a  href="https://luckly.work/categories/" title="分类">分类</a>
                    
                    <a  href="https://luckly.work/tags/" title="标签">标签</a>
                    
                    <a  href="https://luckly.work/archives/" title="归档">归档</a>
                    
                    <a  href="https://luckly.work/about/" title="关于我">关于我</a>
                    
                    <a  href="https://github.com/ITmxs/" title="github">github</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>

    <div id="body">
        <div class="container">
            <div class="col-group">

                <div class="col-8" id="main">
                    
<div class="res-cons">
    <style type="text/css">
    .post-toc {
        position: fixed;
        width: 200px;
        margin-left: -210px;
        padding: 5px 10px;
        font-family: Athelas, STHeiti, Microsoft Yahei, serif;
        font-size: 12px;
        border: 1px solid rgba(0, 0, 0, .07);
        border-radius: 5px;
        background-color: rgba(255, 255, 255, 0.98);
        background-clip: padding-box;
        -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        word-wrap: break-word;
        white-space: nowrap;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        z-index: 999;
        cursor: pointer;
        max-height: 70%;
        overflow-y: auto;
        overflow-x: hidden;
    }

    .post-toc .post-toc-title {
        width: 100%;
        margin: 0 auto;
        font-size: 20px;
        font-weight: 400;
        text-transform: uppercase;
        text-align: center;
    }

    .post-toc .post-toc-content {
        font-size: 15px;
    }

    .post-toc .post-toc-content>nav>ul {
        margin: 10px 0;
    }

    .post-toc .post-toc-content ul {
        padding-left: 20px;
        list-style: square;
        margin: 0.5em;
        line-height: 1.8em;
    }

    .post-toc .post-toc-content ul ul {
        padding-left: 15px;
        display: none;
    }

    @media print,
    screen and (max-width:1057px) {
        .post-toc {
            display: none;
        }
    }
</style>
<div class="post-toc" style="position: absolute; top: 188px;">
    <h2 class="post-toc-title">文章目录</h2>
    <div class="post-toc-content">
        <nav id="TableOfContents">
  <ul>
    <li><a href="#1准备工作">1.准备工作</a></li>
    <li><a href="#2使用流程">2.使用流程</a></li>
    <li><a href="#3封装-shared_preferences">3.封装 shared_preferences</a></li>
  </ul>

  <ul>
    <li><a href="#1导入">1.导入</a></li>
    <li><a href="#2ascii">2.Ascii</a></li>
    <li><a href="#3base64">3.Base64</a></li>
    <li><a href="#4json">4.json</a></li>
    <li><a href="#5utf8">5.utf8</a></li>
    <li><a href="#6latin">6.Latin</a></li>
  </ul>

  <ul>
    <li><a href="#1准备工作-1">1.准备工作</a>
      <ul>
        <li><a href="#11-添加依赖">1.1 添加依赖:</a></li>
        <li><a href="#12-安装">1.2 安装</a></li>
        <li><a href="#13-导入">1.3 导入</a></li>
        <li><a href="#14-注意">1.4 注意</a></li>
      </ul>
    </li>
    <li><a href="#2使用流程-1">2.使用流程</a>
      <ul>
        <li><a href="#21-创建数据库">2.1 创建数据库</a></li>
        <li><a href="#22-创建数据表">2.2 创建数据表</a></li>
        <li><a href="#23-增删改查">2.3 增删改查</a></li>
        <li><a href="#24-批处理-batch">2.4 批处理 Batch</a></li>
        <li><a href="#25-事务">2.5 事务</a></li>
        <li><a href="#26其他">2.6其他</a></li>
      </ul>
    </li>
  </ul>

  <ul>
    <li><a href="#准备工作">准备工作</a></li>
    <li><a href="#2方法">2.方法</a></li>
  </ul>

  <ul>
    <li><a href="#1-目录directory">1. 目录(Directory)</a>
      <ul>
        <li></li>
      </ul>
    </li>
    <li><a href="#2文件file">2.文件(File)</a>
      <ul>
        <li></li>
      </ul>
    </li>
  </ul>
</nav>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        var postToc = $(".post-toc");
        if (postToc.length) {
            var leftPos = $("#main").offset().left;
            if(leftPos<220){
                postToc.css({"width":leftPos-10,"margin-left":(0-leftPos)})
            }

            var t = postToc.offset().top - 20,
                a = {
                    start: {
                        position: "absolute",
                        top: t
                    },
                    process: {
                        position: "fixed",
                        top: 20
                    },
                };
            $(window).scroll(function () {
                var e = $(window).scrollTop();
                e < t ? postToc.css(a.start) : postToc.css(a.process)
            })
        }
    })
</script>
    <article class="post">
        <header>
            <h1 class="post-title">Flutter持久化存储之使用和封装shared_preferences</h1>
        </header>
        <date class="post-meta meta-date">
            2021年8月31日
        </date>
        
        <div class="post-meta">
            <span>|</span>
            
            <span class="meta-category"><a href='/categories/Flutter'>Flutter</a></span>
            
            <span class="meta-category"><a href='/categories/dart'>dart</a></span>
            
        </div>
        
        
        <div class="post-meta">
            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span>
                    阅读</span></span>
        </div>
        
        
        <div class="post-content">
            <p><a href="http://www.ptbird.cn/flutter-video.html">http://www.ptbird.cn/flutter-video.html</a></p>
<p><a href="https://www.jianshu.com/p/a104f0a96594">https://www.jianshu.com/p/a104f0a96594</a></p>
<p><a href="https://blog.csdn.net/beyondforme/article/details/103895229">https://blog.csdn.net/beyondforme/article/details/103895229</a></p>
<p>首先在 pubspec.yaml 文件中添加 shared_preferences 引用并 Packages get</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">dependencies:
  flutter:
    sdk: flutter
 
  <span style="color:#960050;background-color:#1e0010">#</span> The following adds the Cupertino Icons font to your application.
  <span style="color:#960050;background-color:#1e0010">#</span> Use <span style="color:#66d9ef">with</span> the CupertinoIcons <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">for</span> iOS style icons.
  shared_preferences: <span style="color:#f92672">^</span><span style="color:#ae81ff">0.4</span>.<span style="color:#ae81ff">2</span>
</code></pre></div><p>然后封装 SharedPreferences 工具类</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:shared_preferences/shared_preferences.dart&#39;</span>;
 
<span style="color:#75715e">/**
</span><span style="color:#75715e"> * @des SharedPreferences 工具类
</span><span style="color:#75715e"> * @author liyongli 20190522
</span><span style="color:#75715e"> * */</span>
<span style="color:#66d9ef">class</span> <span style="color:#a6e22e">SharedPreferencesDataUtils</span>{
 
  <span style="color:#75715e">// 保存数据
</span><span style="color:#75715e"></span>  Future setUserInfo(key, value) <span style="color:#66d9ef">async</span>{
    SharedPreferences sp <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> SharedPreferences.getInstance();
    sp.setString(key, value);
  }
 
  <span style="color:#75715e">// 获取数据
</span><span style="color:#75715e"></span>  Future getUserInfo(key) <span style="color:#66d9ef">async</span>{
    SharedPreferences sp <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> SharedPreferences.getInstance();
    print(sp.<span style="color:#66d9ef">get</span>(key));
    <span style="color:#66d9ef">return</span> sp.<span style="color:#66d9ef">get</span>(key);
  }
 
  <span style="color:#75715e">// 清除数据
</span><span style="color:#75715e"></span>  Future deleteUserInfo(key) <span style="color:#66d9ef">async</span>{
    SharedPreferences sp <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> SharedPreferences.getInstance();
    sp.remove(key);
  }
 
}
</code></pre></div><p>调用方式</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">    SharedPreferencesDataUtils spDataUtils <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> SharedPreferencesDataUtils();
 
    spDataUtils.setUserInfo(<span style="color:#e6db74">&#34;name&#34;</span>,<span style="color:#e6db74">&#34;Flutter Flutter Flutter&#34;</span>);
    spDataUtils.setUserInfo(<span style="color:#e6db74">&#34;type&#34;</span>,<span style="color:#e6db74">&#34;Save Save Save&#34;</span>);
 
    print(dataUtils.getUserInfo(<span style="color:#e6db74">&#34;name&#34;</span>));
    print(dataUtils.getUserInfo(<span style="color:#e6db74">&#34;type&#34;</span>));
</code></pre></div><p>运行结果</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">    I<span style="color:#f92672">/</span>flutter (<span style="color:#ae81ff">13801</span>)<span style="color:#f92672">:</span> Flutter Flutter Flutter
    I<span style="color:#f92672">/</span>flutter (<span style="color:#ae81ff">13801</span>)<span style="color:#f92672">:</span> Save Save Save
</code></pre></div><h1 id="flutter持久化存储之使用和封装shared_preferences">Flutter持久化存储之使用和封装shared_preferences</h1>
<p>对NSUserDefaults(在iOS上)和SharedPreferences(在Android上)进行了包装，用于持久化的存储一些较为简单的数据，以键值对的方式存储(key-value) ，不建议存储重要的信息。 复杂数据进行数据库持久化存储请看 Flutter持久化存储之sqflite
默认只能存储 int、double、String、List、bool类型，对其进行封装处理为单例模式，并使其具备存储Map和List的能力，并且不用关注类型，存储和读取都更加方便</p>
<h2 id="1准备工作">1.准备工作</h2>
<p>1.1 添加依赖</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#960050;background-color:#1e0010">在</span>pubspec.yaml文件下添加
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">dependencies:
  shared_preferences: <span style="color:#f92672">^</span><span style="color:#ae81ff">0.5</span>.<span style="color:#ae81ff">7</span><span style="color:#f92672">+</span><span style="color:#ae81ff">3</span>

</code></pre></div><p>安装
如果保存了有自动执行则最好，如果没有那么在终端运行flutter packages get命令</p>
<p>导入</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#960050;background-color:#1e0010">‘</span>package<span style="color:#960050;background-color:#1e0010">:</span>shared_preferences<span style="color:#960050;background-color:#1e0010">/</span>shared_preferences<span style="color:#960050;background-color:#1e0010">.</span>dart<span style="color:#960050;background-color:#1e0010">’</span>;
</code></pre></div><h2 id="2使用流程">2.使用流程</h2>
<p>2.1 获取实例对象</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">SharedPreferences prefs <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> SharedPreferences.getInstance();
</code></pre></div><p>2.2 设置值</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 目前仅支持5种类型的存储,Map(对象)需要先转换成JSON字符串之后 再进行存储 本质上还是存储字符串
</span><span style="color:#75715e">// 1. int
</span><span style="color:#75715e"></span>prefs.setInt(<span style="color:#e6db74">&#39;age&#39;</span>,<span style="color:#ae81ff">18</span>);
<span style="color:#75715e">// 2. double
</span><span style="color:#75715e"></span>prefs.setDouble(<span style="color:#e6db74">&#39;source&#39;</span>,<span style="color:#ae81ff">99.9</span>);
<span style="color:#75715e">// 3. String
</span><span style="color:#75715e"></span>prefs.setString(<span style="color:#e6db74">&#39;name&#39;</span>,<span style="color:#e6db74">&#39;Marco&#39;</span>);
<span style="color:#75715e">// 4. bool
</span><span style="color:#75715e"></span>prefs.setBool(<span style="color:#e6db74">&#39;isADC&#39;</span>,<span style="color:#66d9ef">true</span>);
<span style="color:#75715e">// 5. List&lt;String&gt;
</span><span style="color:#75715e"></span>prefs.setStringList(<span style="color:#e6db74">&#39;strList&#39;</span>,[<span style="color:#e6db74">&#39;str1&#39;</span>,<span style="color:#e6db74">&#39;str2&#39;</span>]);
<span style="color:#75715e">// 6. Map 使用convert中的方法将Map转换成字符串进行存储 取出时也需要进行处理
</span><span style="color:#75715e"></span>prefs.setString(<span style="color:#e6db74">&#39;info&#39;</span>,JsonEncoder().convert({<span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#34;Marco&#34;</span>,<span style="color:#e6db74">&#34;type&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#34;ADC&#34;</span>}));

</code></pre></div><p>2.3 读取值</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 0. get 可以取出任意类型的value
</span><span style="color:#75715e"></span>prefs.<span style="color:#66d9ef">get</span>(<span style="color:#e6db74">&#39;age&#39;</span>);
<span style="color:#75715e">// 1. int 
</span><span style="color:#75715e"></span>prefs.getInt(<span style="color:#e6db74">&#39;age&#39;</span>);
<span style="color:#75715e">// 2.double
</span><span style="color:#75715e"></span>prefs.getDouble(<span style="color:#e6db74">&#39;source&#39;</span>);
<span style="color:#75715e">// 3. String
</span><span style="color:#75715e"></span>prefs.getString(<span style="color:#e6db74">&#39;name&#39;</span>);
<span style="color:#75715e">// 4. bool 
</span><span style="color:#75715e"></span>prefs.getBool(<span style="color:#e6db74">&#39;isADC&#39;</span>);
<span style="color:#75715e">// 5.List&lt;String&gt;
</span><span style="color:#75715e"></span>prefs.getStringList(<span style="color:#e6db74">&#39;strList&#39;</span>);
<span style="color:#75715e">// 6. Map 取出的是JSON字符串 因此需要进行转换
</span><span style="color:#75715e"></span>JsonDecoder().convert(prefs.getString(<span style="color:#e6db74">&#34;info&#34;</span>))

</code></pre></div><p>2.4 其他操作</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 1. remove(key)     删除值 根据key删除保存的键值对
</span><span style="color:#75715e"></span>prefs.remove(<span style="color:#e6db74">&#39;age&#39;</span>);
<span style="color:#75715e">// 2.containsKey(key)  是否存储的键值对中是否包含给定的key
</span><span style="color:#75715e"></span>prefs.remove(<span style="color:#e6db74">&#39;source&#39;</span>);
<span style="color:#75715e">// 3. clear()  清空所有键值对
</span><span style="color:#75715e"></span>prefs.clear();
<span style="color:#75715e">// 4. getKeys() 获取所有的key 返回一个Set&lt;String&gt; 
</span><span style="color:#75715e"></span>prefs.getKeys();

</code></pre></div><h2 id="3封装-shared_preferences">3.封装 shared_preferences</h2>
<p>封装和使用都较为简单，只是对不同类型的数据进行判断和处理，如果没搞明白，直接使用也是完全没有问题的
这里的代码是完整的main.dart的代码，包含了封装的类以及每一个方法的使用</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:flutter/material.dart&#39;</span>;
<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:shared_preferences/shared_preferences.dart&#39;</span>;
<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;dart:convert&#39;</span>;
<span style="color:#75715e">/// 封装SharedPreferences为单例模式
</span><span style="color:#75715e"></span><span style="color:#66d9ef">class</span> <span style="color:#a6e22e">PersistentStorage</span>{
  <span style="color:#75715e">/// 静态私有实例对象
</span><span style="color:#75715e"></span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">final</span> _instance<span style="color:#f92672">=</span>PersistentStorage._init();
  <span style="color:#75715e">/// 工厂构造函数 返回实例对象
</span><span style="color:#75715e"></span>  <span style="color:#66d9ef">factory</span> PersistentStorage()<span style="color:#f92672">=&gt;</span>_instance;
  <span style="color:#75715e">/// SharedPreferences对象
</span><span style="color:#75715e"></span>  <span style="color:#66d9ef">static</span> SharedPreferences _storage;
  <span style="color:#75715e">/// 命名构造函数 用于初始化SharedPreferences实例对象
</span><span style="color:#75715e"></span>  PersistentStorage._init(){
    _initStorage();
  } 
  <span style="color:#75715e">// 之所以这个没有写在 _init中，是因为SharedPreferences.getInstance是一个异步的方法 需要用await接收它的值
</span><span style="color:#75715e"></span>  _initStorage()<span style="color:#66d9ef">async</span>{
    <span style="color:#75715e">// 若_不存在 则创建SharedPreferences实例
</span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span>(_storage<span style="color:#f92672">==</span><span style="color:#66d9ef">null</span>)
      _storage<span style="color:#f92672">=</span><span style="color:#66d9ef">await</span> SharedPreferences.getInstance();
  }
  <span style="color:#75715e">/// 设置存储
</span><span style="color:#75715e"></span>  setStorage(<span style="color:#66d9ef">String</span> key,<span style="color:#66d9ef">dynamic</span> value)<span style="color:#66d9ef">async</span>{
    <span style="color:#66d9ef">await</span> _initStorage();
    <span style="color:#66d9ef">String</span> type;
    <span style="color:#75715e">// 监测value的类型 如果是Map和List,则转换成JSON，以字符串进行存储
</span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span>(value <span style="color:#66d9ef">is</span> Map<span style="color:#f92672">||</span>value <span style="color:#66d9ef">is</span> List){
      type<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;String&#39;</span>;
      value<span style="color:#f92672">=</span>JsonEncoder().convert(value);
    }
    <span style="color:#75715e">// 否则 获取value的类型的字符串形式
</span><span style="color:#75715e"></span>    <span style="color:#66d9ef">else</span>{
      type<span style="color:#f92672">=</span>value.runtimeType.toString();
    }
    <span style="color:#75715e">// 根据value不同的类型 用不同的方法进行存储
</span><span style="color:#75715e"></span>    <span style="color:#66d9ef">switch</span> (type) {
      <span style="color:#66d9ef">case</span> <span style="color:#e6db74">&#39;String&#39;</span><span style="color:#f92672">:</span>
        _storage.setString(key, value);
        <span style="color:#66d9ef">break</span>;
      <span style="color:#66d9ef">case</span> <span style="color:#e6db74">&#39;int&#39;</span><span style="color:#f92672">:</span>
        _storage.setInt(key, value);
        <span style="color:#66d9ef">break</span>;
      <span style="color:#66d9ef">case</span> <span style="color:#e6db74">&#39;double&#39;</span><span style="color:#f92672">:</span>
        _storage.setDouble(key, value);
        <span style="color:#66d9ef">break</span>;
      <span style="color:#66d9ef">case</span> <span style="color:#e6db74">&#39;bool&#39;</span><span style="color:#f92672">:</span>
        _storage.setBool(key, value);
        <span style="color:#66d9ef">break</span>;
    }
  }
  <span style="color:#75715e">/// 获取存储 注意：返回的是一个Future对象 要么用await接收 要么在.then中接收
</span><span style="color:#75715e"></span>  Future<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">dynamic</span><span style="color:#f92672">&gt;</span> getStorage(<span style="color:#66d9ef">String</span> key)<span style="color:#66d9ef">async</span>{
    <span style="color:#66d9ef">await</span> _initStorage();
    <span style="color:#75715e">// 获取key对应的value
</span><span style="color:#75715e"></span>    <span style="color:#66d9ef">dynamic</span> value<span style="color:#f92672">=</span>_storage.<span style="color:#66d9ef">get</span>(key);
    <span style="color:#75715e">// 判断value是不是一个json的字符串 是 则解码
</span><span style="color:#75715e"></span>    <span style="color:#66d9ef">if</span>(_isJson(value)){
      <span style="color:#66d9ef">return</span> JsonDecoder().convert(value);
    }<span style="color:#66d9ef">else</span>{
      <span style="color:#75715e">// 不是 则直接返回
</span><span style="color:#75715e"></span>      <span style="color:#66d9ef">return</span> value;
    }
  }
  <span style="color:#75715e">/// 是否包含某个key 
</span><span style="color:#75715e"></span>  Future<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">bool</span><span style="color:#f92672">&gt;</span> hasKey(<span style="color:#66d9ef">String</span> key)<span style="color:#66d9ef">async</span>{
    <span style="color:#66d9ef">await</span> _initStorage();
    <span style="color:#66d9ef">return</span> _storage.containsKey(key);
  }
  <span style="color:#75715e">/// 删除key指向的存储 如果key存在则删除并返回true，否则返回false
</span><span style="color:#75715e"></span>  Future<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">bool</span><span style="color:#f92672">&gt;</span> removeStorage(<span style="color:#66d9ef">String</span> key)<span style="color:#66d9ef">async</span>{
    <span style="color:#66d9ef">await</span> _initStorage();
    <span style="color:#66d9ef">if</span>(<span style="color:#66d9ef">await</span> hasKey(key)){
      <span style="color:#66d9ef">await</span> _storage.remove(key);
      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
    }<span style="color:#66d9ef">else</span>{
      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span>;
    }
    <span style="color:#75715e">// return  _storage.remove(key);
</span><span style="color:#75715e"></span>  }

  <span style="color:#75715e">/// 清空存储 并总是返回true
</span><span style="color:#75715e"></span>  Future<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">bool</span><span style="color:#f92672">&gt;</span> clear()<span style="color:#66d9ef">async</span>{
    <span style="color:#66d9ef">await</span> _initStorage();
    _storage.clear();
    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
  }

  <span style="color:#75715e">/// 获取所有的key 类型为Set&lt;String&gt;
</span><span style="color:#75715e"></span>  Future<span style="color:#f92672">&lt;</span>Set<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">String</span><span style="color:#f92672">&gt;&gt;</span> getKeys()<span style="color:#66d9ef">async</span>{
    <span style="color:#66d9ef">await</span> _initStorage();
    <span style="color:#66d9ef">return</span> _storage.getKeys();
  }


  <span style="color:#75715e">// 判断是否是JSON字符串
</span><span style="color:#75715e"></span>  _isJson(<span style="color:#66d9ef">dynamic</span> value){
    <span style="color:#66d9ef">try</span>{
      <span style="color:#75715e">// 如果value是一个json的字符串 则不会报错 返回true
</span><span style="color:#75715e"></span>      JsonDecoder().convert(value);
      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
    }<span style="color:#66d9ef">catch</span>(e){
      <span style="color:#75715e">// 如果value不是json的字符串 则报错 进入catch 返回false
</span><span style="color:#75715e"></span>      <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span>;
    }
  }
}

main(List<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">String</span><span style="color:#f92672">&gt;</span> args) <span style="color:#66d9ef">async</span>{
  runApp(MaterialApp(
    home: Scaffold(
      appBar: AppBar(title: Text(<span style="color:#e6db74">&#34;封装SharedPreferences&#34;</span>),),
      body: Container(),
    ),
  ));
  <span style="color:#75715e">// 创建两个实例对象
</span><span style="color:#75715e"></span>  <span style="color:#66d9ef">var</span> ps<span style="color:#f92672">=</span>PersistentStorage();
  <span style="color:#66d9ef">var</span> ps2<span style="color:#f92672">=</span>PersistentStorage();
  <span style="color:#75715e">// 单例模式 对象是同一个对象
</span><span style="color:#75715e"></span>  print(<span style="color:#e6db74">&#34;两个对象是否相等:</span><span style="color:#e6db74">${</span>ps<span style="color:#f92672">==</span>ps2<span style="color:#e6db74">}</span><span style="color:#e6db74">&#34;</span>);  <span style="color:#75715e">// true 
</span><span style="color:#75715e"></span>  <span style="color:#75715e">// 1. 存储所有类型的值
</span><span style="color:#75715e"></span>  ps.setStorage(<span style="color:#e6db74">&#39;Map&#39;</span>,{<span style="color:#e6db74">&#34;key&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#34;value&#34;</span>});        <span style="color:#75715e">// 存储Map
</span><span style="color:#75715e"></span>  ps.setStorage(<span style="color:#e6db74">&#39;int&#39;</span>,<span style="color:#ae81ff">1</span>);                      <span style="color:#75715e">// 存储int
</span><span style="color:#75715e"></span>  ps.setStorage(<span style="color:#e6db74">&#39;double&#39;</span>,<span style="color:#ae81ff">1.0</span>);                 <span style="color:#75715e">// 存储double
</span><span style="color:#75715e"></span>  ps.setStorage(<span style="color:#e6db74">&#39;bool&#39;</span>,<span style="color:#66d9ef">true</span>);                  <span style="color:#75715e">// 存储bool
</span><span style="color:#75715e"></span>  ps.setStorage(<span style="color:#e6db74">&#39;String&#39;</span>, <span style="color:#e6db74">&#34;Hello World&#34;</span>);      <span style="color:#75715e">// 存储String
</span><span style="color:#75715e"></span>  ps.setStorage(<span style="color:#e6db74">&#39;List&#39;</span>,[<span style="color:#ae81ff">1</span>,<span style="color:#66d9ef">true</span>,<span style="color:#e6db74">&#39;String&#39;</span>,<span style="color:#ae81ff">1.0</span>]); <span style="color:#75715e">// 存储List
</span><span style="color:#75715e"></span>
  <span style="color:#75715e">// 除setStorage以外 获取的方法的返回值全部都是Future类型
</span><span style="color:#75715e"></span>  <span style="color:#75715e">// 因此需要使用await获取 或者 在其.then方法中获取值
</span><span style="color:#75715e"></span>
  <span style="color:#75715e">// 2. 根据key获取存储的值
</span><span style="color:#75715e"></span>  <span style="color:#75715e">// 2.1 通过await 直接获取存储的值 注意 await只能在async方法中使用
</span><span style="color:#75715e"></span>  print(<span style="color:#66d9ef">await</span> ps.getStorage(<span style="color:#e6db74">&#39;Map&#39;</span>));                  <span style="color:#75715e">// {key: value}
</span><span style="color:#75715e"></span>  <span style="color:#75715e">// 2.2 在then中获取存储的值 
</span><span style="color:#75715e"></span>  ps.getStorage(<span style="color:#e6db74">&#39;Map&#39;</span>).then((value) <span style="color:#f92672">=&gt;</span> print(value)); <span style="color:#75715e">// {key: value}
</span><span style="color:#75715e"></span>
  <span style="color:#75715e">// 同上
</span><span style="color:#75715e"></span>
  <span style="color:#75715e">// 3. 根据key移除存储的值
</span><span style="color:#75715e"></span>  print(<span style="color:#66d9ef">await</span> ps.removeStorage(<span style="color:#e6db74">&#34;List&#34;</span>));      <span style="color:#75715e">// true  删除成功
</span><span style="color:#75715e"></span>  print(<span style="color:#66d9ef">await</span> ps.removeStorage(<span style="color:#e6db74">&#39;nothing&#39;</span>));   <span style="color:#75715e">// false 删除失败
</span><span style="color:#75715e"></span>
  <span style="color:#75715e">// 4. 是否包含某个key 
</span><span style="color:#75715e"></span>  print(<span style="color:#66d9ef">await</span> ps.hasKey(<span style="color:#e6db74">&#39;map&#39;</span>));   <span style="color:#75715e">// 存在   true  
</span><span style="color:#75715e"></span>  print(<span style="color:#66d9ef">await</span> ps.hasKey(<span style="color:#e6db74">&#34;List&#34;</span>));  <span style="color:#75715e">// 不存在 false 
</span><span style="color:#75715e"></span>
  <span style="color:#75715e">// 5. 获取所有的key
</span><span style="color:#75715e"></span>  print(<span style="color:#66d9ef">await</span> ps.getKeys());

  <span style="color:#75715e">// 6. 清空所有存储 
</span><span style="color:#75715e"></span>  print(<span style="color:#66d9ef">await</span> ps.clear());  <span style="color:#75715e">//一直都会返回true 
</span><span style="color:#75715e"></span>}


</code></pre></div><p>未封装的shared_preferences的使用还是比较简单的，主要是Map类型的存储不是很方便，需要借助convert进行转换，关于convert可以参考Flutter中编解码Convert基本使用 。
经过封装之后还是非常实用的，用法也比较简单，如果对你有所帮助，点赞鼓励可好~~</p>
<h1 id="flutter中编解码convert基本使用">Flutter中编解码Convert基本使用</h1>
<h2 id="1导入">1.导入</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;dart:convert&#39;</span>;     
<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;dart:typed_data&#39;</span>;  <span style="color:#75715e">// Uint8List需要导入这个
</span><span style="color:#75715e"></span>
</code></pre></div><h2 id="2ascii">2.Ascii</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 创建一个 AsciiCodec 对象 
</span><span style="color:#75715e"></span>AsciiCodec ac<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> AsciiCodec();
<span style="color:#75715e">// 编码 将ascii字符串转换成UintList类型 无法编码中文 会报错
</span><span style="color:#75715e"></span>Uint8List list<span style="color:#f92672">=</span>ac.encode(<span style="color:#e6db74">&#34;Hello Dart&#34;</span>);
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// Uint8List list=AsciiEncoder().convert(&#34;Hello Dart&#34;);
</span><span style="color:#75715e"></span>print(list);  <span style="color:#75715e">// [72, 101, 108, 108, 111, 32, 68, 97, 114, 116]
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 解码 将UintList转换成ascii字符串
</span><span style="color:#75715e"></span><span style="color:#66d9ef">String</span> str<span style="color:#f92672">=</span>ac.decode(list);
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// String str=AsciiDecoder().convert(list);
</span><span style="color:#75715e"></span>print(str);    <span style="color:#75715e">// Hello Dart
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 解码流 即将Stram&lt;List&lt;int&gt;&gt;类型转换成ascii字符串 
</span><span style="color:#75715e"></span>ac.decodeStream(Stream.value(list)).then((value)<span style="color:#f92672">=&gt;</span>print(value)); <span style="color:#75715e">// Hello Dart
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 编解码器的名称
</span><span style="color:#75715e"></span>print(ac.name);  <span style="color:#75715e">// us-ascii
</span><span style="color:#75715e"></span>
</code></pre></div><h2 id="3base64">3.Base64</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">AsciiCodec ac<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> AsciiCodec();
Uint8List list<span style="color:#f92672">=</span><span style="color:#66d9ef">await</span> ac.encode(<span style="color:#e6db74">&#34;Hello Dart&#34;</span>);
print(list);  <span style="color:#75715e">//  [72, 101, 108, 108, 111, 32, 68, 97, 114, 116]
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// Base64Codec允许base64将字节编码为ASCII字符串，并将有效编码解码回字节,始终是4的倍数。
</span><span style="color:#75715e"></span>Base64Codec bc<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> Base64Codec();
<span style="color:#75715e">// 编码
</span><span style="color:#75715e"></span><span style="color:#66d9ef">String</span> str<span style="color:#f92672">=</span>bc.encode(list);
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// String str=new Base64Encoder().convert(list);
</span><span style="color:#75715e"></span>print(str);  <span style="color:#75715e">//   SGVsbG8gRGFydA==
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 解码
</span><span style="color:#75715e"></span>Uint8List list2<span style="color:#f92672">=</span>bc.decode(str);
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// Uint8List list2=new Base64Decoder().convert(str);
</span><span style="color:#75715e"></span>print(list2); <span style="color:#75715e">//  [72, 101, 108, 108, 111, 32, 68, 97, 114, 116]
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 验证并标准化source的base64编码数据 是base64则照常输出 不是则进行填充或报错
</span><span style="color:#75715e">// 看是否是4的倍数 如果多一个字符 则报错 多两个及以上 则填充
</span><span style="color:#75715e"></span>print(bc.normalize(str));

</code></pre></div><h2 id="4json">4.json</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">JsonCodec jc<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> JsonCodec();
<span style="color:#75715e">// JS中的对象就是这里的Map
</span><span style="color:#75715e"></span>print({}.runtimeType);
<span style="color:#75715e">// 将Map转换成JSON
</span><span style="color:#75715e"></span><span style="color:#66d9ef">Object</span> person<span style="color:#f92672">=</span>jc.encode({<span style="color:#e6db74">&#39;name&#39;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#34;zs&#34;</span>});
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// Object person=new JsonEncoder().convert({&#39;name&#39;:&#34;zs&#34;});
</span><span style="color:#75715e"></span>print(person);
<span style="color:#75715e">// 将JSON转换成Map
</span><span style="color:#75715e"></span>Map<span style="color:#f92672">&lt;</span><span style="color:#66d9ef">String</span>,<span style="color:#66d9ef">dynamic</span><span style="color:#f92672">&gt;</span> str<span style="color:#f92672">=</span>jc.decode(person);
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// Map&lt;String,dynamic&gt; str=new JsonDecoder().convert(person);
</span><span style="color:#75715e"></span>print(str);

<span style="color:#75715e">// 将对象或JSON字符串 转换成一个UTF-8数组(Uint8List)
</span><span style="color:#75715e"></span>Uint8List person2<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> JsonUtf8Encoder().convert({<span style="color:#e6db74">&#39;name&#39;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;zs&#39;</span>});
print(person2);

</code></pre></div><h2 id="5utf8">5.utf8</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">Utf8Codec utf<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> Utf8Codec();

<span style="color:#75715e">// 将字符串编码为Uint8List
</span><span style="color:#75715e"></span>Uint8List list<span style="color:#f92672">=</span>utf.encode(<span style="color:#e6db74">&#34;Hello Dart&#34;</span>);
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// Uint8List list=new Utf8Encoder().convert(&#34;Hello Dart&#34;);
</span><span style="color:#75715e"></span>print(list);

<span style="color:#75715e">// 将Uint8List解码为字符串
</span><span style="color:#75715e"></span><span style="color:#66d9ef">String</span> str<span style="color:#f92672">=</span>utf.decode(list);
<span style="color:#75715e">// 等价于
</span><span style="color:#75715e">// String str=new Utf8Decoder().convert(list);
</span><span style="color:#75715e"></span>print(str);

<span style="color:#75715e">// 将流解码
</span><span style="color:#75715e"></span>utf.decodeStream(Stream.value(list)).then((value) <span style="color:#f92672">=&gt;</span> print(value));

print(utf.name);
}

</code></pre></div><h2 id="6latin">6.Latin</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// Latin1编码是单字节编码(无法编码中文)，向下兼容ASCII
</span><span style="color:#75715e"></span>Latin1Codec lc<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> Latin1Codec();
Uint8List list<span style="color:#f92672">=</span>lc.encode(<span style="color:#e6db74">&#34;Hello Dart&#34;</span>);
<span style="color:#75715e">// Uint8List list2=lc.encode(&#34;你好 Dart&#34;); //报错
</span><span style="color:#75715e"></span>print(list);

<span style="color:#66d9ef">String</span> str<span style="color:#f92672">=</span>lc.decode(list);
print(str);

</code></pre></div><h1 id="flutter持久化存储之sqflite操作数据库详细使用">Flutter持久化存储之sqflite操作数据库详细使用</h1>
<p>前言
sqflite是一个轻量的关系型数据库，以表的形式将较为复杂的数据存储到.db文件中(数据库)，同时支持安卓和IOS，简单数据可直接使用 shared_preferences</p>
<h2 id="1准备工作-1">1.准备工作</h2>
<h3 id="11-添加依赖">1.1 添加依赖:</h3>
<p>在pubspec.yaml文件下添加
path_provider是用来处理路径相关的操作</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart">dependencies:
  sqflite: <span style="color:#f92672">^</span><span style="color:#ae81ff">1.3</span>.<span style="color:#ae81ff">0</span><span style="color:#f92672">+</span><span style="color:#ae81ff">2</span>
  path_provider: <span style="color:#f92672">^</span><span style="color:#ae81ff">1.6</span>.<span style="color:#ae81ff">9</span>
</code></pre></div><h3 id="12-安装">1.2 安装</h3>
<p>如果保存了有自动执行则最好，如果没有那么在终端运行flutter packages get命令</p>
<h3 id="13-导入">1.3 导入</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:sqflite/sqflite.dart&#39;</span>;
<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;package:path_provider/path_provider.dart&#39;</span>;

</code></pre></div><h3 id="14-注意">1.4 注意</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"> <span style="color:#75715e">// SQLite支持的数据类型  不支持bool和DateTime
</span><span style="color:#75715e"></span> <span style="color:#75715e">// SQL类型 ==== Dart类型
</span><span style="color:#75715e"></span> <span style="color:#75715e">// integer ==== int
</span><span style="color:#75715e"></span> <span style="color:#75715e">// real    ==== num
</span><span style="color:#75715e"></span> <span style="color:#75715e">// text    ==== String
</span><span style="color:#75715e"></span> <span style="color:#75715e">// blob    ==== Uint8List
</span><span style="color:#75715e"></span>
</code></pre></div><h2 id="2使用流程-1">2.使用流程</h2>
<h3 id="21-创建数据库">2.1 创建数据库</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 数据库文件路径：可以根据自己的需求自己定 这里使用的是外部存储可见的目录
</span><span style="color:#75715e">// 可以将路径打印出来 在手机上找到它
</span><span style="color:#75715e"></span><span style="color:#66d9ef">String</span> databasePath<span style="color:#f92672">=</span>(<span style="color:#66d9ef">await</span> getExternalStorageDirectory()).path<span style="color:#f92672">+</span><span style="color:#e6db74">&#34;/demo.db&#34;</span>;

<span style="color:#75715e">// 打开数据库  (若想数据库只能读取则使用openReadOnlyDatabase())
</span><span style="color:#75715e">// 1 若数据库不存在 则创建数据库
</span><span style="color:#75715e">// 2 若数据库存在 version大于当前数据库version 则升级
</span><span style="color:#75715e">// 3 若数据库存在 version小于当前数据库version 则降级
</span><span style="color:#75715e">// 4 若数据库存在 version等于当前数据库version 则不变
</span><span style="color:#75715e"></span> Database database<span style="color:#f92672">=</span><span style="color:#66d9ef">await</span> openDatabase(databasePath,version: <span style="color:#ae81ff">2</span>,
  readOnly: <span style="color:#66d9ef">false</span>,      <span style="color:#75715e">//   是否只读
</span><span style="color:#75715e"></span>  singleInstance: <span style="color:#66d9ef">true</span>, <span style="color:#75715e">//   是否单例
</span><span style="color:#75715e"></span>  <span style="color:#75715e">// 第一个被调用的可选回调 配置数据库使用SQL语句配置
</span><span style="color:#75715e"></span>  onConfigure: (Database database)<span style="color:#66d9ef">async</span>{
    <span style="color:#66d9ef">await</span> database.execute(<span style="color:#e6db74">&#34;PRAGMA foreign_keys = ON&#34;</span>);
    print(<span style="color:#e6db74">&#34;配置数据库&#34;</span>);
  },
  <span style="color:#75715e">// 创建数据库回调
</span><span style="color:#75715e"></span>  onCreate: (Database database,<span style="color:#66d9ef">int</span> version)<span style="color:#66d9ef">async</span>{
    print(<span style="color:#e6db74">&#34;版本:</span><span style="color:#e6db74">$</span>version<span style="color:#e6db74"> 数据库创建成功&#34;</span>);
  },
  <span style="color:#75715e">// 数据库降级回调
</span><span style="color:#75715e"></span>  onDowngrade: (Database database,<span style="color:#66d9ef">int</span> oldVersion,<span style="color:#66d9ef">int</span> newVersion)<span style="color:#66d9ef">async</span>{
    print(<span style="color:#e6db74">&#34;版本</span><span style="color:#e6db74">$</span>oldVersion<span style="color:#e6db74"> 降级到 </span><span style="color:#e6db74">$</span>newVersion<span style="color:#e6db74">&#34;</span>);
  },
  <span style="color:#75715e">// 数据库升级回调
</span><span style="color:#75715e"></span>  onUpgrade: (Database database,<span style="color:#66d9ef">int</span> oldVersion,<span style="color:#66d9ef">int</span> newVersion)<span style="color:#66d9ef">async</span>{
    print(<span style="color:#e6db74">&#34;版本</span><span style="color:#e6db74">$</span>oldVersion<span style="color:#e6db74"> 升级到 </span><span style="color:#e6db74">$</span>newVersion<span style="color:#e6db74">&#34;</span>);
  },
  <span style="color:#75715e">// 数据库打开回调
</span><span style="color:#75715e"></span>  onOpen: (Database database){
    print(<span style="color:#e6db74">&#34;数据库打开成功&#34;</span>);
  },
);

</code></pre></div><h3 id="22-创建数据表">2.2 创建数据表</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 使用execute方法执行SQL语句 注意：execute执行的SQL是没有返回值的
</span><span style="color:#75715e"></span>database.execute(<span style="color:#e6db74">&#39;CREATE TABLE Test (id INTEGER PRIMARY KEY, name TEXT, value INTEGER, age REAL)&#39;</span>);

</code></pre></div><h3 id="23-增删改查">2.3 增删改查</h3>
<p>2.3.1 where和whereArgs的使用</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 在查询和更新删除等语句中，会使用到where和whereArgs作为条件及条件参数
</span><span style="color:#75715e">// 此处以查询为例 更新和删除请举一反三
</span><span style="color:#75715e">// 查询test表中 name为zs并且age为18的记录 
</span><span style="color:#75715e">// where中 and代表并且(都满足) or代表或者(满足其一)
</span><span style="color:#75715e">// where中的?为占位符 会依照顺序被后面whereArgs中的数据替换
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> database.query(<span style="color:#e6db74">&#39;test&#39;</span>,where:<span style="color:#e6db74">&#34;name=? and age=?&#34;</span>,whereArgs: [<span style="color:#e6db74">&#34;zs&#34;</span>,<span style="color:#ae81ff">18</span>]).then((value) <span style="color:#f92672">=&gt;</span> print(value));

</code></pre></div><p>2.3.2 插入数据</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 插入数据  
</span><span style="color:#75715e">//1.insert(表名,{&#34;键&#34;:值},conflictAlgorithm(冲突算法:枚举类型)) 返回行数
</span><span style="color:#75715e"></span>database.insert(<span style="color:#e6db74">&#39;test&#39;</span>,{<span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;zs&#39;</span>,<span style="color:#e6db74">&#34;age&#34;</span><span style="color:#f92672">:</span><span style="color:#ae81ff">18</span>}).then((value) <span style="color:#f92672">=&gt;</span> print(value));
<span style="color:#75715e">// 2. 使用SQL语句进行插入 
</span><span style="color:#75715e">// database.rawInsert(&#34;SQL语句&#34;);
</span><span style="color:#75715e"></span>
</code></pre></div><p>2.3.3 删除数据</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 删除数据 
</span><span style="color:#75715e">// 1.delete(&#34;表名&#34;,where(条件),whereArgs(条件参数))
</span><span style="color:#75715e">// 此处为寻找name为zs的记录
</span><span style="color:#75715e"></span>database.delete(<span style="color:#e6db74">&#39;test&#39;</span>,where: <span style="color:#e6db74">&#34;name=?&#34;</span>,whereArgs: [<span style="color:#e6db74">&#34;zs&#34;</span>]);  
<span style="color:#75715e">// 2. 使用SQL语句进行删除
</span><span style="color:#75715e">// database.rawDelete(&#34;SQL语句&#34;);
</span><span style="color:#75715e"></span>
</code></pre></div><p>2.3.4 更新数据</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 更新数据
</span><span style="color:#75715e">// 1.update(&#34;表名&#34;,要修改的内容{&#39;键&#39;:值},where(条件),whereArgs(条件参数),conflictAlgorithm(冲突算法：枚举类型))
</span><span style="color:#75715e">// 将name为zs的记录的name改为ls，age改为18
</span><span style="color:#75715e"></span>database.update(<span style="color:#e6db74">&#39;test&#39;</span>, {<span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;ls&#39;</span>,<span style="color:#e6db74">&#34;age&#34;</span><span style="color:#f92672">:</span><span style="color:#ae81ff">18</span>},where: <span style="color:#e6db74">&#34;name=?&#34;</span>,whereArgs: [<span style="color:#e6db74">&#39;zs&#39;</span>]);
<span style="color:#75715e">// 2.使用SQL语句进行更新
</span><span style="color:#75715e">// database.rawUpdate(&#34;SQL语句&#34;);
</span><span style="color:#75715e"></span>
</code></pre></div><p>2.3.5 查询数据</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 查询数据
</span><span style="color:#75715e">// 1.query(表名,{distinct,columns(返回哪些字段),where(条件),
</span><span style="color:#75715e">// whereArgs(条件参数),groupBy(分组),having(分组后的进行条件查询),
</span><span style="color:#75715e">//  orderBy(排序),limit(一次读几条),offset(起始位置)}) 返回读取到的结果(列表)
</span><span style="color:#75715e">// 若没有查询条件 则返回这个表的数据
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> database.query(<span style="color:#e6db74">&#39;test&#39;</span>,                 <span style="color:#75715e">//查询的表名
</span><span style="color:#75715e"></span>  distinct: <span style="color:#66d9ef">true</span>,                              <span style="color:#75715e">// 不重复
</span><span style="color:#75715e"></span>  where:<span style="color:#e6db74">&#34;value=? and age=?&#34;</span>,whereArgs: [<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">18</span>], <span style="color:#75715e">// 查询 value为1并且age为18的记录
</span><span style="color:#75715e"></span>  columns: [<span style="color:#e6db74">&#34;name&#34;</span>,<span style="color:#e6db74">&#34;age&#34;</span>],                     <span style="color:#75715e">// 返回的记录只包含name和age两个字段
</span><span style="color:#75715e"></span>  groupBy: <span style="color:#e6db74">&#34;age&#34;</span>,                              <span style="color:#75715e">// 根据age分组
</span><span style="color:#75715e"></span>  orderBy: <span style="color:#e6db74">&#34;age&#34;</span>,                              <span style="color:#75715e">// 根据age排序
</span><span style="color:#75715e"></span>  limit: <span style="color:#ae81ff">10</span>,                                   <span style="color:#75715e">// 一次读取10条记录
</span><span style="color:#75715e"></span>  offset: <span style="color:#ae81ff">5</span>                                    <span style="color:#75715e">// 从第5条记录开始查询
</span><span style="color:#75715e"></span>);
<span style="color:#75715e">// 2. 使用SQL语句进行查询
</span><span style="color:#75715e">// database.rawQuery(&#34;SQL语句&#34;);
</span><span style="color:#75715e"></span>
</code></pre></div><h3 id="24-批处理-batch">2.4 批处理 Batch</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 批处理SQL语句 往Batch中添加语句 但是这些语句并不会执行 需要调用commit方法 然后一次性执行
</span><span style="color:#75715e"></span>Batch batch<span style="color:#f92672">=</span>database.batch();
batch.insert(<span style="color:#e6db74">&#34;test&#34;</span>,{<span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;ls&#39;</span>});
batch.insert(<span style="color:#e6db74">&#34;test&#34;</span>,{<span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;ww&#39;</span>});
<span style="color:#75715e">// noResult 是否不需要结果  continueOnError遇到异常是否继续执行 
</span><span style="color:#75715e"></span>batch.commit(noResult: <span style="color:#66d9ef">true</span>,continueOnError: <span style="color:#66d9ef">true</span>).then((value) <span style="color:#f92672">=&gt;</span> print(value));

</code></pre></div><h3 id="25-事务">2.5 事务</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 事务
</span><span style="color:#75715e">// 在事务中执行SQL语句 若发生异常 则进行回滚 即全部SQL语句无效
</span><span style="color:#75715e">// 四大特征:
</span><span style="color:#75715e">// 1. 原子性：即事务中的语句为一个整体 要么全部执行 要么全不执行
</span><span style="color:#75715e">// 2. 一致性：保持数据的一致性 如转账 转账过后的总金额需要保持一致
</span><span style="color:#75715e">// 3. 隔离性：多个事务并发时  互不干涉内部数据 处理的数据都是别的事务处理前或处理后的数据
</span><span style="color:#75715e">// 4. 持久性：事务提交后 数据是持久不可更改的
</span><span style="color:#75715e"></span>
database.transaction((txn)<span style="color:#66d9ef">async</span>{
  <span style="color:#75715e">// txn基本有database中所有的操作 基本可以当做database使用
</span><span style="color:#75715e"></span>  txn.insert(<span style="color:#e6db74">&#39;test&#39;</span>,{<span style="color:#e6db74">&#34;name&#34;</span><span style="color:#f92672">:</span><span style="color:#e6db74">&#39;Rob&#39;</span>});
});

</code></pre></div><h3 id="26其他">2.6其他</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 数据库是否打开
</span><span style="color:#75715e">// print(database.isOpen);
</span><span style="color:#75715e"></span>
<span style="color:#75715e">//  获取默认数据库存放的路径
</span><span style="color:#75715e"></span>getDatabasesPath().then((value) <span style="color:#f92672">=&gt;</span> print(<span style="color:#e6db74">&#34;默认数据库路径&#34;</span><span style="color:#f92672">+</span>value));

<span style="color:#75715e">// 根据路径查看数据库是否存在
</span><span style="color:#75715e"></span>databaseExists(databasePath).then((value) <span style="color:#f92672">=&gt;</span> print(<span style="color:#e6db74">&#34;数据库是否存在:&#34;</span><span style="color:#f92672">+</span>value.toString()));

<span style="color:#75715e">// 设置数据库版本
</span><span style="color:#75715e"></span>database.setVersion(<span style="color:#ae81ff">666</span>);

<span style="color:#75715e">// 获取数据库版本
</span><span style="color:#75715e"></span>database.getVersion().then((value) <span style="color:#f92672">=&gt;</span> print(value));

<span style="color:#75715e">// 关闭数据库(数据库文件还在)
</span><span style="color:#75715e">// database.close(); 
</span><span style="color:#75715e"></span>
<span style="color:#75715e">//  删除数据库(数据库文件不在)
</span><span style="color:#75715e">// await deleteDatabase(databasePath);
</span><span style="color:#75715e"></span>
</code></pre></div><p>根据官方文档和源码注解以及尝试所得，若有所帮，点赞一下</p>
<h1 id="flutter插件之path_provider">Flutter插件之path_provider</h1>
<h2 id="准备工作">准备工作</h2>
<p>1.1 添加依赖
在pubspec.yaml文件下添加
1
dependencies:
path_provider: ^1.6.9
1
2
1.2 安装
如果保存了有自动执行则最好，如果没有那么在终端运行flutter packages get命令
1
1.3 导入
import &lsquo;package:path_provider/path_provider.dart&rsquo;;
1</p>
<h2 id="2方法">2.方法</h2>
<ol>
<li>2.1 获取临时文件路径(IOS和安卓通用)</li>
</ol>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 获取不会备份并且随时会被删除的临时目录(IOS和安卓通用)
</span><span style="color:#75715e"></span>getTemporaryDirectory().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>2.2 获取应用支持目录(IOS和安卓通用)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 用于存储应用支持的目录 这个目录对于用户是不可见的 (IOS和安卓通用)
</span><span style="color:#75715e"></span>getApplicationSupportDirectory().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>2.3 获取应用文件目录(IOS和安卓通用)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 用于放置用户生成的数据或不能有应用程序重新创建的数据 用户不可见(IOS和安卓通用)
</span><span style="color:#75715e"></span>getApplicationDocumentsDirectory().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>2.4 获取应用持久存储目录路径(仅IOS可用)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 应用程序可以存储持久化、备份和用户不可见的文件的目录路径
</span><span style="color:#75715e"></span>getLibraryDirectory().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>2.5 获取外部存储目录(仅安卓可用)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 获取外部存储目录 用户可见
</span><span style="color:#75715e"></span>getExternalStorageDirectory().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>2.6 获取外部存储目录列表(仅安卓可用)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 可以存储应用程序特定数据的目录 
</span><span style="color:#75715e">// 这些路径通常驻留在外部存储上 用户可见 如单独的分区或SD卡(可以有多个 所以是列表)
</span><span style="color:#75715e"></span>getExternalStorageDirectories().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>2.7 获取外部缓存目录(仅安卓可用)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 可以存储应用程序特定外部存储数据的目录 
</span><span style="color:#75715e">// 这些路径通常驻留在外部存储上，如单独的分区或SD卡(可以有多个 所以是列表)
</span><span style="color:#75715e"></span>getExternalCacheDirectories().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>2.8 获取下载目录(仅桌面可用 安卓和IOS报错)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 获取下载路径 
</span><span style="color:#75715e"></span>getDownloadsDirectory().then((value) <span style="color:#f92672">=&gt;</span> print(value));
</code></pre></div><p>插件的内容较少，使用也比较简单，仅仅只是用于获取路径，并没有操作文件和目录的功能，因此，需要搭配Director和File等进行操作。</p>
<h1 id="flutter中目录directory和文件file常用操作">Flutter中目录(Directory)和文件(File)常用操作</h1>
<h2 id="1-目录directory">1. 目录(Directory)</h2>
<h4 id="11-导入">1.1 导入</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;dart:io&#39;</span>;       <span style="color:#75715e">// Directory所在的包
</span><span style="color:#75715e"></span><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;dart:convert&#39;</span>;  <span style="color:#75715e">// 
</span><span style="color:#75715e"></span>
</code></pre></div><h4 id="12创建实例">1.2创建实例</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 根据路径字符串创建目录对象
</span><span style="color:#75715e"></span>Directory dir<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> Directory(<span style="color:#e6db74">&#34;assets</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">files&#34;</span>);
<span style="color:#75715e">//  根据Uri对象创建目录对象
</span><span style="color:#75715e">// Directory dir=new Directory.fromUri(Uri(path: &#34;assets&#34;));
</span><span style="color:#75715e">// 根据Uint8List路径创建实例 Utf8Encoder().convert()将字符串转换成Uint8List
</span><span style="color:#75715e">// Directory.fromRawPath(Utf8Encoder().convert(&#34;assets\\files&#34;));
</span><span style="color:#75715e"></span>
</code></pre></div><h4 id="13属性">1.3属性</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// String path 获取此目录的路径
</span><span style="color:#75715e"></span>print(dir.path);

<span style="color:#75715e">// Uri 返回表示目录位置的uri
</span><span style="color:#75715e"></span>print(dir.uri);

<span style="color:#75715e">// 父目录的Directory对象
</span><span style="color:#75715e"></span>print(dir.parent);

<span style="color:#75715e">// absolute 返回一个绝对路径的Directory对象
</span><span style="color:#75715e"></span>print(dir.absolute);

<span style="color:#75715e">// 判断是否是绝对路径
</span><span style="color:#75715e"></span>print(dir.isAbsolute);

</code></pre></div><h4 id="14方法">1.4方法</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// create({bool recursive: false}) → Future&lt;Directory&gt; 根据路径创建目录 recursive是否递归创建 递归创建的意思就是 即便路径中有目录不存在 全部都会创建出来
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> dir.create(recursive: <span style="color:#66d9ef">true</span>);

<span style="color:#75715e">// createTemp([String prefix]) → Future&lt;Directory&gt; 在此目录中创建一个临时目录,其他随机字符将附加到prefix以产生唯一的目录名称. 
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> dir.createTemp();

<span style="color:#75715e">// list({bool recursive: false, bool followLinks: true}) → Stream&lt;FileSystemEntity&gt;
</span><span style="color:#75715e">// recursive是否递归列出子目录 followLinks是否允许link
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> dir.list().toList().then((value) <span style="color:#f92672">=&gt;</span> print(value));

<span style="color:#75715e">// rename(String newPath) → Future&lt;Directory&gt; 重命名目录
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// resolveSymbolicLinks() → Future&lt;String&gt; 解析文件系统对象相对于当前工作目录的路径 解析路径上的所有符号链接，并解析所有..和. 路径段 返回一个类似绝对路径的字符串
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> dir.absolute.resolveSymbolicLinks().then((value) <span style="color:#f92672">=&gt;</span> print(value));

<span style="color:#75715e">// 查看目录是否存在
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> dir.exists().then((value) <span style="color:#f92672">=&gt;</span> print(value));

<span style="color:#75715e">// delete({bool recursive: false}) → Future&lt;FileSystemEntity&gt; 删除文件目录 
</span><span style="color:#75715e">// 默认情况下 只能删除空目录 将recursive设置为true 才可以递归删除目录中所有的文件和目录
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> dir.delete(recursive: <span style="color:#66d9ef">true</span>).then((value) <span style="color:#f92672">=&gt;</span> print(value)).catchError((err)<span style="color:#f92672">=&gt;</span>{print(err)});

<span style="color:#75715e">// stat() → Future&lt;FileStat&gt; 查看目录信息
</span><span style="color:#75715e">// type directory                     类型：目录
</span><span style="color:#75715e">// changed 2020-05-29 11:14:50.000    文件系统对象的数据或元数据的最后更改时间
</span><span style="color:#75715e">// modified 2020-05-29 11:15:01.000   最后一次更改文件系统对象的数据的时间
</span><span style="color:#75715e">// accessed 2020-05-29 11:15:01.000   上次访问文件系统对象的数据的时间
</span><span style="color:#75715e">// mode rwxrwxrwx                     文件系统对象的模式 r(read) w(write) x(execute) 读写执行
</span><span style="color:#75715e">// size 0                             文件大小
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> dir.stat().then((value) <span style="color:#f92672">=&gt;</span> print(value));

</code></pre></div><h2 id="2文件file">2.文件(File)</h2>
<h4 id="21-导入">2.1 导入</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;dart:io&#39;</span>;
<span style="color:#66d9ef">import</span> <span style="color:#e6db74">&#39;dart:convert&#39;</span>;

</code></pre></div><h4 id="21创建实例">2.1创建实例</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 根据文件路径字符串创建文件实例
</span><span style="color:#75715e"></span>File file<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> File(<span style="color:#e6db74">&#34;assets/index.txt&#34;</span>);
<span style="color:#75715e">// 根据Uri对象创建文件实例
</span><span style="color:#75715e"></span>File file2<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> File.fromUri(Uri(path: <span style="color:#e6db74">&#34;assets/index.txt&#34;</span>));
Utf8Codec utf<span style="color:#f92672">=</span>Utf8Codec();
<span style="color:#75715e">// 根据Uint8List文件路径创建实例 Utf8Encoder().convert()将字符串转换成Uint8List
</span><span style="color:#75715e"></span>File file3<span style="color:#f92672">=</span>File.fromRawPath(Utf8Encoder().convert(<span style="color:#e6db74">&#34;assets</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">files</span><span style="color:#ae81ff">\\</span><span style="color:#e6db74">index.txt&#34;</span>));

</code></pre></div><h4 id="23属性">2.3属性</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 打印一下file实例对象
</span><span style="color:#75715e"></span>print(file);   <span style="color:#75715e">// File: &#39;assets\files\index.txt&#39;
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 返回绝对路径的File实例
</span><span style="color:#75715e"></span>print(file.absolute); <span style="color:#75715e">// File: &#39;C:\Users\Administrator.PW6NUH21X31RM79\Desktop\Dart\assets\files\index.txt&#39;
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 获取文件路径
</span><span style="color:#75715e"></span>print(file.path); <span style="color:#75715e">// assets\files\index.txt
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 是否是绝对路径
</span><span style="color:#75715e"></span>print(file.isAbsolute);  <span style="color:#75715e">// fasle
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 获取父目录的Directory对象
</span><span style="color:#75715e"></span>print(file.parent);  <span style="color:#75715e">// Directory: &#39;assets\files&#39;
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 获取uri
</span><span style="color:#75715e"></span>print(file.uri);   <span style="color:#75715e">// assets/files/index.txt
</span><span style="color:#75715e"></span>
</code></pre></div><h4 id="24方法">2.4方法</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dart" data-lang="dart"><span style="color:#75715e">// 1. copy(String newPath) 复制文件  copySync(String newPath) 同步复制文件
</span><span style="color:#75715e">// 新路径的目录必须存在 否则报错
</span><span style="color:#75715e">// 若新路径下已有同名文件 则覆盖
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> file.copy(<span style="color:#e6db74">&#34;assets/image/index.txt&#34;</span>).then((value) <span style="color:#f92672">=&gt;</span> print(value));

<span style="color:#75715e">// 2. create({bool recursive: false})创建文件 
</span><span style="color:#75715e">// createSync({bool recursive: false}) 同步创建文件
</span><span style="color:#75715e">// 可选命名参数:recursive 默认false, 
</span><span style="color:#75715e">// 若为true  则路径中有目录不存在时 会递归创建目录 
</span><span style="color:#75715e">// 若为false 则路径中的目录不存在时 会报错
</span><span style="color:#75715e"></span>File file2<span style="color:#f92672">=</span><span style="color:#66d9ef">new</span> File(<span style="color:#e6db74">&#34;assets/files/text.txt&#34;</span>);
<span style="color:#66d9ef">await</span> file2.create();

<span style="color:#75715e">// 3.lastAccessed() 获取文件上次访问时间  lastAccessedSync()同步获取
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.lastAccessed()); <span style="color:#75715e">// 2020-05-30 10:39:35.000
</span><span style="color:#75715e">// setLastAccessed(Datetime time)  修改文件上次访问时间 +Sync 同步
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> file.setLastAccessed(<span style="color:#66d9ef">new</span> DateTime.now());

<span style="color:#75715e">// 4. lastModified() 获取文件最后修改时间 lastModifiedSync()同步获取
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.lastModified());
<span style="color:#75715e">// setLastModified(DateTime time)  修改文件的最后修改时间 +Sync 同步
</span><span style="color:#75715e"></span><span style="color:#66d9ef">await</span> file.setLastModified(<span style="color:#66d9ef">new</span> DateTime.now());

<span style="color:#75715e">// 5. length()获取文件长度(字节数) lengthSync() 同步获取
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.length());

<span style="color:#75715e">// 6. rename(String newPath) 重命名 renameSync(String newPath)
</span><span style="color:#75715e">// 若新路径和旧路径在同一个目录下 那么仅仅是重命名
</span><span style="color:#75715e">// 若新路径和旧路径不在一个目录下 那么就是移动文件加重命名 
</span><span style="color:#75715e"></span>file.rename(<span style="color:#e6db74">&#34;index.txt&#34;</span>);

<span style="color:#75715e">// 7. 读取
</span><span style="color:#75715e">// 7.1 readAsString()以字符串形式读取 readAsStringSync() 同步读取
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.readAsString());
<span style="color:#75715e">// 7.2 readAsBytes()以字节形式读取   readAsBytesSync() 同步读取
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.readAsBytes());     
<span style="color:#75715e">// 7.3 readAsLines()按行读取 返回字符串数组    readAsLinesSync() 同步读取
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.readAsLines());

<span style="color:#75715e">// 8. 写入
</span><span style="color:#75715e">// 8.1 writeAsString() 以字符串方式写入
</span><span style="color:#75715e"></span>file.writeAsString(<span style="color:#e6db74">&#34;Dart &#34;</span>,
mode: FileMode.append,<span style="color:#75715e">// 写入的模式 append(追加写入) read(只读) write(读写) writeOnly(只写)  writeOnlyAppend(只追加)
</span><span style="color:#75715e"></span>flush: <span style="color:#66d9ef">true</span>,    <span style="color:#75715e">// 如果flush设置为`true` 则写入的数据将在返回之前刷新到文件系统 
</span><span style="color:#75715e"></span>encoding:utf8,  <span style="color:#75715e">// 设置编码
</span><span style="color:#75715e"></span>);
<span style="color:#75715e">// 8.2 writeAsBytes() 写入字节数组 参数同上
</span><span style="color:#75715e"></span>file.writeAsBytes([<span style="color:#ae81ff">1</span>,<span style="color:#ae81ff">2</span>,<span style="color:#ae81ff">3</span>]);

<span style="color:#75715e">// 9. delete() 删除文件  deleteSync() 同步删除文件
</span><span style="color:#75715e">// await file.delete();
</span><span style="color:#75715e"></span>
<span style="color:#75715e">// 10. exists() 检查文件是否存在 existsSync() 同步检查文件是否存在
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.exists());

<span style="color:#75715e">// 11. resolveSymbolicLinks() 解析文件系统对象相对于当前工作目录的路径 +Sync同步
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.resolveSymbolicLinks());

<span style="color:#75715e">// 12. stat()  获取文件对应的FileStat对象 StatSync() 同步获取
</span><span style="color:#75715e">// 包含type(类型) 
</span><span style="color:#75715e">// changed(文件系统对象的数据的最后修改时间) 
</span><span style="color:#75715e">// modified(最后一次更改文件系统对象的数据的时间)
</span><span style="color:#75715e">// accessed(上次访问时间)
</span><span style="color:#75715e">// size(文件大小)  
</span><span style="color:#75715e"></span>print(<span style="color:#66d9ef">await</span> file.stat());

<span style="color:#75715e">// 13和14涉及流(Stream)的操作 之后会继续更新异步和流
</span><span style="color:#75715e">// 13. openRead() 为文件的内容创建一个Stream(流) 
</span><span style="color:#75715e"></span>print(file.openRead());

<span style="color:#75715e">// 14. openWrite() 为文件创建一个IOSink,使用结束需要释放资源
</span><span style="color:#75715e">// print(file.openWrite());  // 先注释 不然会截断文件
</span><span style="color:#75715e"></span>
</code></pre></div>
        </div>

        
<div class="post-archive">
    <ul class="post-copyright">
        <li><strong>原文作者：</strong><a rel="author" href="https://luckly.work/">luckly</a></li>
        <li style="word-break:break-all"><strong>原文链接：</strong><a href="https://luckly.work/post/flutter_package/Flutter%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8%E4%B9%8B%E4%BD%BF%E7%94%A8%E5%92%8C%E5%B0%81%E8%A3%85shared_preferences/">https://luckly.work/post/flutter_package/Flutter%E6%8C%81%E4%B9%85%E5%8C%96%E5%AD%98%E5%82%A8%E4%B9%8B%E4%BD%BF%E7%94%A8%E5%92%8C%E5%B0%81%E8%A3%85shared_preferences/</a></li>
        <li><strong>版权声明：</strong>本作品采用<a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/">知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议</a>进行许可，非商业转载请注明出处（作者，原文链接），商业转载请联系作者获得授权。</li>
    </ul>
</div>
<br/>



        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/post/dart/dart-%E5%A6%82%E4%BD%95%E5%9C%A8%E6%89%A9%E5%B1%95%E6%96%B9%E6%B3%95%E4%B8%AD%E5%8F%8D%E8%BD%AC%E5%88%97%E8%A1%A8/">Dart如何在扩展方法中反转列表</a></li>
        
        <li><a href="/post/dart/dart-%E5%A6%82%E4%BD%95%E5%9C%A8flutter%E4%B8%AD%E5%8F%8D%E8%BD%AC%E6%96%87%E6%9C%AC/">Dart如何在flutter中反转文本</a></li>
        
        <li><a href="/post/dart/dartdart-%E5%A6%82%E4%BD%95%E5%B1%95%E5%B9%B3%E4%B8%80%E4%B8%AA%E5%88%97%E8%A1%A8/">Dart如何展平一个列表</a></li>
        
        <li><a href="/post/flutter_widget/flutter%E7%BB%84%E4%BB%B6Tooltip%E4%B8%8EOverlay/">Flutter组件Tooltip与Overlay</a></li>
        
        <li><a href="/post/flutter_widget/flutter%E7%BB%84%E4%BB%B6Draggable%E4%B8%8EDragTarget/">Flutter组件Draggable与DragTarget</a></li>
        
    </ul>
</div>


        <div class="post-meta meta-tags">
            
            <ul class="clearfix">
                
                <li><a href='/tags/Flutter'>Flutter</a></li>
                
                <li><a href='/tags/dart'>dart</a></li>
                
            </ul>
            
        </div>
    </article>
    
    

    
    
    <div class="post bg-white">
      <script src="https://utteranc.es/client.js"
            repo= "https://github.com/ITmxs/repo"
            issue-term="pathname"
            theme="github-light"
            crossorigin="anonymous"
            async>
      </script>
    </div>
    
</div>

                    <footer id="footer">
    <div>
        &copy; 2021 <a href="https://luckly.work/">早起的年轻人 By luckly</a>
        
        | <a rel="nofollow" target="_blank" href="http://beian.miit.gov.cn/">粤ICP备2021号-1</a>
        
    </div>
    <br />
    <div>
        <div class="github-badge">
            <a href="https://juejin.cn/user/3843548384077192" target="_black" rel="nofollow"><span class="badge-subject">Powered by</span><span class="badge-value bg-blue">掘金</span></a>
        </div>
        <div class="github-badge">
            <a href="https://space.bilibili.com/480883651" target="_black"><span class="badge-subject">Design by</span><span class="badge-value bg-brightgreen">早起的年轻人</span></a>
        </div>
        <div class="github-badge">
            <a href="https://cloud.tencent.com/developer/user/6702670" target="_black"><span class="badge-subject">Theme</span><span class="badge-value bg-yellowgreen">云社区</span></a>
        </div>
    </div>
</footer>


    
    <script type="text/javascript">
        window.MathJax = {
            tex2jax: {
                inlineMath: [['$', '$']],
                processEscapes: true
                }
            };
    </script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script><script src="https://cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src='/js/totop.js?v=0.0.0' async=""></script>



    <script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




    <script src='/js/douban.js'></script>
    <script src="/js/copy-to-clipboard.js"></script>

                </div>

                <div id="secondary">
    <section class="widget">
        <form id="search" action='https://luckly.work/search/' method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="https://luckly.work/">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="https://luckly.work/post/nginx/nginx%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9/" title="Nginx文件内容">Nginx文件内容</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/nginx/nginx%E6%9E%81%E7%AE%80%E6%95%99%E7%A8%8B/" title="Nginx极简教程">Nginx极简教程</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/nginx/%E5%8D%81%E5%88%86%E9%92%9F%E5%85%A5%E9%97%A8nginx/" title="十分钟入门Nginx">十分钟入门Nginx</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/go/Goland%E8%BF%9C%E7%A8%8B%E5%BC%80%E5%8F%91%E9%85%8D%E7%BD%AE/" title="Goland远程开发配置">Goland远程开发配置</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E8%AF%BB%E4%B9%A6/%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90/" title="域名解析">域名解析</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/git/%E6%8F%90%E4%BA%A4%E8%BF%87%E7%A8%8B%E7%9C%81%E7%95%A5%E6%9F%90%E4%BA%9B%E6%96%87%E4%BB%B6/" title="提交过程省略某些文件">提交过程省略某些文件</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/flutter_tips/Flutter_DropdownButton%E7%A4%BA%E4%BE%8B/" title="Flutter_DropdownButton示例">Flutter_DropdownButton示例</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/flutter_tips/Flutter_ExpansionPanelList%E5%92%8CExpansionPanelList.radio%E7%A4%BA%E4%BE%8B/" title="Flutter_ExpansionPanelList和ExpansionPanelList">Flutter_ExpansionPanelList和ExpansionPanelList</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/flutter_tips/Flutter%E5%BE%AE%E4%BF%A1%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E8%B7%B3%E5%9B%9EApp%E6%8C%87%E5%AE%9A%E9%A1%B5%E9%9D%A2/" title="Flutter微信分享链接跳回App指定页面">Flutter微信分享链接跳回App指定页面</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F/%E5%A4%96%E5%8C%85%E5%8F%AF%E8%83%BD%E7%9A%84%E9%97%AE%E9%A2%98/" title="外包可能的问题">外包可能的问题</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title"><a href='/categories/'>分类</a></h3>
<ul class="widget-list">
    
    <li><a href="https://luckly.work/categories/Flutter/">Flutter (326)</a></li>
    
    <li><a href="https://luckly.work/categories/IT/">IT (2)</a></li>
    
    <li><a href="https://luckly.work/categories/Kotlin/">Kotlin (2)</a></li>
    
    <li><a href="https://luckly.work/categories/Mysql/">Mysql (1)</a></li>
    
    <li><a href="https://luckly.work/categories/nginx/">nginx (1)</a></li>
    
    <li><a href="https://luckly.work/categories/Vue/">Vue (6)</a></li>
    
    <li><a href="https://luckly.work/categories/YouTube%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD/">YouTube视频下载 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/android/">android (6)</a></li>
    
    <li><a href="https://luckly.work/categories/dart/">dart (96)</a></li>
    
    <li><a href="https://luckly.work/categories/Flutter/">Flutter (28)</a></li>
    
    <li><a href="https://luckly.work/categories/gin/">gin (25)</a></li>
    
    <li><a href="https://luckly.work/categories/git/">git (4)</a></li>
    
    <li><a href="https://luckly.work/categories/Go/">Go (102)</a></li>
    
    <li><a href="https://luckly.work/categories/gorm/">gorm (4)</a></li>
    
    <li><a href="https://luckly.work/categories/grpc/">grpc (1)</a></li>
    
    <li><a href="https://luckly.work/categories/html/">html (3)</a></li>
    
    <li><a href="https://luckly.work/categories/ios/">ios (1)</a></li>
    
    <li><a href="https://luckly.work/categories/linux/">linux (1)</a></li>
    
    <li><a href="https://luckly.work/categories/nginx/">nginx (6)</a></li>
    
    <li><a href="https://luckly.work/categories/python/">python (35)</a></li>
    
    <li><a href="https://luckly.work/categories/read/">读书笔记 (6)</a></li>
    
    <li><a href="https://luckly.work/categories/redis/">redis (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B8%AA%E4%BA%BA%E8%B5%84%E6%96%99/">个人资料 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B9%A6%E5%8D%95/">书单 (8)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B9%A6%E8%AF%84/">书评 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统管理师 (19)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统项目管理师 (25)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%8E%9F%E5%88%99/">原则 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%8E%9F%E7%94%9F%E9%80%9A%E8%AE%AF/">原生通讯 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%9F%BA%E7%A1%80/">基础 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%A4%8D%E5%88%A9%E6%95%88%E5%BA%94/">复利效应 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/">安装教程 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%B0%91%E6%9C%89%E4%BA%BA%E8%B5%B0%E7%9A%84%E8%B7%AF/">少有人走的路 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%BF%83%E8%AF%AD/">心语 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E6%8F%92%E4%BB%B6/">插件 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E6%95%99%E5%AD%A6/">教学 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%8E%8B%E9%98%B3%E6%98%8E/">王阳明 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%94%B5%E5%AD%90%E4%B9%A6/">电子书 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%99%BB%E9%99%86%E8%A1%A8%E5%8D%95/">登陆表单 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%A8%BB%E7%9B%9B%E5%92%8C%E5%A4%AB/">稻盛和夫 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%A9%B7%E7%88%B8%E7%88%B8%E5%AF%8C%E7%88%B8%E7%88%B8/">穷爸爸富爸爸 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%B2%BE%E8%BF%9B/">精进 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%BC%96%E7%A8%8B/">编程 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%99%9A%E5%B9%BB/">虚幻 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B4%A2%E5%8A%A1%E8%87%AA%E7%94%B1%E4%B9%8B%E8%B7%AF/">财务自由之路 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%91%E6%AD%A5/">跑步 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82/">路由传参 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%AF%E7%BA%BF/">路线 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%BD%AF%E4%BB%B6%E5%AE%9E%E6%96%BD/">软件实施 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%98%B3%E6%98%8E%E5%BF%83%E5%AD%A6/">阳明心学 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%A1%B9%E7%9B%AE/">项目 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%AD%85%E5%8A%9B/">魅力 (1)</a></li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title"><a href='/tags/'>标签</a></h3>
<div class="tagcloud">
    
    <a href="https://luckly.work/tags/flutter/">flutter</a>
    
    <a href="https://luckly.work/tags/IT/">IT</a>
    
    <a href="https://luckly.work/tags/Kotlin/">Kotlin</a>
    
    <a href="https://luckly.work/tags/Mysql/">Mysql</a>
    
    <a href="https://luckly.work/tags/nginx/">nginx</a>
    
    <a href="https://luckly.work/tags/Vue/">Vue</a>
    
    <a href="https://luckly.work/tags/YouTube%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD/">YouTube视频下载</a>
    
    <a href="https://luckly.work/tags/android/">android</a>
    
    <a href="https://luckly.work/tags/dart/">dart</a>
    
    <a href="https://luckly.work/tags/flutter/">flutter</a>
    
    <a href="https://luckly.work/tags/gin/">gin</a>
    
    <a href="https://luckly.work/tags/git/">git</a>
    
    <a href="https://luckly.work/tags/go/">go</a>
    
    <a href="https://luckly.work/tags/gorm/">gorm</a>
    
    <a href="https://luckly.work/tags/grpc/">grpc</a>
    
    <a href="https://luckly.work/tags/html/">html</a>
    
    <a href="https://luckly.work/tags/ios/">ios</a>
    
    <a href="https://luckly.work/tags/linux/">linux</a>
    
    <a href="https://luckly.work/tags/nginx/">nginx</a>
    
    <a href="https://luckly.work/tags/python/">python</a>
    
    <a href="https://luckly.work/tags/redis/">redis</a>
    
    <a href="https://luckly.work/tags/%E4%B8%AA%E4%BA%BA%E8%B5%84%E6%96%99/">个人资料</a>
    
    <a href="https://luckly.work/tags/%E4%B9%A6%E5%8D%95/">书单</a>
    
    <a href="https://luckly.work/tags/%E4%B9%A6%E8%AF%84/">书评</a>
    
    <a href="https://luckly.work/tags/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统管理师</a>
    
    <a href="https://luckly.work/tags/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统项目管理师</a>
    
    <a href="https://luckly.work/tags/%E5%85%A5%E9%97%A8/">入门</a>
    
    <a href="https://luckly.work/tags/%E5%8E%9F%E5%88%99/">原则</a>
    
    <a href="https://luckly.work/tags/%E5%8E%9F%E7%94%9F%E9%80%9A%E8%AE%AF/">原生通讯</a>
    
    <a href="https://luckly.work/tags/%E5%9F%BA%E7%A1%80/">基础</a>
    
    <a href="https://luckly.work/tags/%E5%A4%8D%E5%88%A9%E6%95%88%E5%BA%94/">复利效应</a>
    
    <a href="https://luckly.work/tags/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/">安装教程</a>
    
    <a href="https://luckly.work/tags/%E5%B0%91%E6%9C%89%E4%BA%BA%E8%B5%B0%E7%9A%84%E8%B7%AF/">少有人走的路</a>
    
    <a href="https://luckly.work/tags/%E5%BF%83%E8%AF%AD/">心语</a>
    
    <a href="https://luckly.work/tags/%E6%8F%92%E4%BB%B6/">插件</a>
    
    <a href="https://luckly.work/tags/%E6%95%99%E5%AD%A6/">教学</a>
    
    <a href="https://luckly.work/tags/%E7%8E%8B%E9%98%B3%E6%98%8E/">王阳明</a>
    
    <a href="https://luckly.work/tags/%E7%94%B5%E5%AD%90%E4%B9%A6/">电子书</a>
    
    <a href="https://luckly.work/tags/%E7%99%BB%E9%99%86%E8%A1%A8%E5%8D%95/">登陆表单</a>
    
    <a href="https://luckly.work/tags/%E7%A8%BB%E7%9B%9B%E5%92%8C%E5%A4%AB/">稻盛和夫</a>
    
    <a href="https://luckly.work/tags/%E7%A9%B7%E7%88%B8%E7%88%B8%E5%AF%8C%E7%88%B8%E7%88%B8/">穷爸爸富爸爸</a>
    
    <a href="https://luckly.work/tags/%E7%B2%BE%E8%BF%9B/">精进</a>
    
    <a href="https://luckly.work/tags/%E7%BC%96%E7%A8%8B/">编程</a>
    
    <a href="https://luckly.work/tags/%E8%99%9A%E5%B9%BB/">虚幻</a>
    
    <a href="https://luckly.work/tags/%E8%AF%97/">诗</a>
    
    <a href="https://luckly.work/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/">读书笔记</a>
    
    <a href="https://luckly.work/tags/%E8%B4%A2%E5%8A%A1%E8%87%AA%E7%94%B1%E4%B9%8B%E8%B7%AF/">财务自由之路</a>
    
    <a href="https://luckly.work/tags/%E8%B7%91%E6%AD%A5/">跑步</a>
    
    <a href="https://luckly.work/tags/%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82/">路由传参</a>
    
    <a href="https://luckly.work/tags/%E8%B7%AF%E7%BA%BF/">路线</a>
    
    <a href="https://luckly.work/tags/%E8%BD%AF%E4%BB%B6%E5%AE%9E%E6%96%BD/">软件实施</a>
    
    <a href="https://luckly.work/tags/%E9%80%9A%E8%AE%AF%E5%BD%95/">通讯录</a>
    
    <a href="https://luckly.work/tags/%E9%98%B3%E6%98%8E%E5%BF%83%E5%AD%A6/">阳明心学</a>
    
    <a href="https://luckly.work/tags/%E9%A1%B9%E7%9B%AE/">项目</a>
    
    <a href="https://luckly.work/tags/%E9%AD%85%E5%8A%9B/">魅力</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="http://www.topgoer.com/" title="枯藤">枯藤</a>
        </li>
        
        <li>
            <a target="_blank" href="https://gorm.cn/zh_CN/docs/index.html" title="gorm">gorm</a>
        </li>
        
        <li>
            <a target="_blank" href="https://docs.python.org/zh-cn/3/tutorial/index.html" title="python">python</a>
        </li>
        
        <li>
            <a target="_blank" href="https://www.liwenzhou.com/" title="李文周">李文周的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="http://www.xbzweb.com/" title="小包子的博客">小包子的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="https://www.flysnow.org/" title="飞雪无情的博客">飞雪无情的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="https://sliverhorn.com/" title="sliverhorn的博客">sliverhorn的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="http://yuedu.baidu.com/ebook/14a722970740be1e640e9a3e" title="Android Gradle权威指南">Android Gradle权威指南</a>
        </li>
        
        <li>
            <a target="_blank" href="https://gesdh.cn/" title="小格子">格子导航</a>
        </li>
        
        <li>
            <a target="_blank" href="https://itachi.xyz/" title="阿林">itachi&#39;s Blog</a>
        </li>
        
        <li>
            <a target="_blank" href="https://darjun.github.io/" title="大俊">大俊Blog</a>
        </li>
        
        <li>
            <a target="_blank" href="https://geektutu.com/post/quick-golang.html" title="极客兔兔">极客兔兔Blog</a>
        </li>
        
        <li>
            <a target="_blank" href="http://zxfcumtcs.github.io/" title="赵雪峰">雪峰Blog</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="https://luckly.work/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
            </div>
        </div>
    </div>
</body>

</html>